<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <ul>
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
  </ul>
  <script>
    // 1.全局作用域    函数外部的内容    全局变量和全局函数
    // 2.局部作用域     函数内部的作用域  局部变量，局部函数

    var x = 88;
    function say() {
      var z = 99;//局部变量 
      y = 100;//全局变量  不推荐的写法 
      function a() { }//局部函数
    }
    // a()   //局部函数无法外部访问
    say()
    // console.log(z) //函数的局部变量  无法外部访问
    function run() {
      say()
    }
    //3.动态作用域 使用this改变
    var name = "小点声"
    function cat() {
      console.log(this.name)
    }
    cat();
    var obj = {
      name: "大点声"
    }
    var res = cat.bind(obj);
    res();
    //4.块级作用域 1.let和const产生块级作用域  
    if (true) {
      let mynum = 888;
      console.log(mynum)
    } else {
      let age = 99;
    }
    // 5.let和const不能重复声明
    let k = 88;
    // let k = 100;// 报错  不能重复声明

    // 6.不能变量提升
    function hh() {
      // console.log(x) //报错 let声明不存在变量提升
      let x = 99;
    }
    // 7const 声明常量 声明后不能重新赋值
    const myname = "ccc"
    // myname = "kkkk"// 报错  const不能重新赋值 

    const obj = {
      name: 333
    }
    //  8 所谓暂时性死区，就是不能在初始化之前使用变量。
    if (true) {
      // val的报错不是value is not defined”  因为块级作用域种可以查看到val变量 只是不能使用
      console.log(val) //Cannot access 'value' before initialization
      let val = 888;
    }


    // 点击事件发生  for循环执行完毕 j 是全局变量  变为4
    //点击事件发生  for循环执行完毕  如果用let 声明 j为局部变量 不会受到j++的干扰
    // var lis = document.querySelectorAll("li")
    // for (let j = 0; j < lis.length; j++) {
    //   lis[j].onclick = function () {
    //     console.log(j)
    //   }
    // }
    // console.log(mynum) //报错   let 在if语句中产生作用域



    // setTimeout执行的时候 for循环执行完毕  i是全局变量 以变为5
    // setTimeout执行的时候 for循环执行完毕 用let声明 i是局部变量 不受i++干扰
    // for (let i = 0; i < 5; i++) {
    //   setTimeout(function () {
    //     console.log(i)
    //   }, 2000)
    // }
    // js 时间循环机制
    //线程和进程

    // 进程与线程的区别

    //     1. 线程是程序执行的最小单位，而进程是操作系统分配资源的最小单位；

    //     2. 一个进程由一个或多个线程组成，线程是一个进程中代码的不同执行路线

    //     3. 进程之间相互独立，但同一进程下的各个线程之间共享程序的内存空间(包括代码段，数据集，堆等)及一些进程级的资源(如打开文件和信

    // 号等) ，某进程内的线程在其他进程不可见；

    //     4. 调度和切换：线程上下文切换比进程上下文切换要快得多

    // js是一个单线程语言
    // 线程中 分为同步任务和异步任务

    // 同步任务、异步任务

    // JavaScript 单线程中的任务分为同步任务和异步任务。同步任务会在调用栈中按照顺序排队等待主线程执行，
    //   异步任务则会在异步有了结果后将注册的回调函数添加到任务队列(消息队列)中等待主线程空闲的时候，
    //   也就是栈内被清空的时候，被读取到栈中等待主线程执行。任务队列是先进先出的数据结构。

    // 有哪些异步任务
    // setTimeout()  setInterval()
    // Promise()    ajax


    // 宏任务(macro - task) 、微任务(micro - task)

    // 除了广义的同步任务和异步任务，JavaScript 单线程中的异步任务可以细分为宏任务和微任务。

    // macro - task包括：script(整体代码), setTimeout, setInterval,    

    // micro - task包括：process.nextTick, Promises, Object.observe

    // 先执行宏任务 在执行微任务
    console.log(1);
    setTimeout(function () { //宏任务
      console.log(2);
    })
    var promise = new Promise(function (resolve, reject) {
      console.log(3);
      resolve();
    })
    promise.then(function () { //微任务
      console.log(4);
    })
    console.log(5);
  // 1 3 5 4 2
//  1  5 同步任务先执行



  </script>
</body>

</html>